﻿using System.ComponentModel;
using System.Linq;
using CoreEx.Common.Extensions;
using CoreEx.Common.Ioc;
using CoreEx.Services;
using LinFu.IoC.Configuration;
using LinFu.IoC.Interfaces;
using LinFu.IoC;
using Mono.Cecil;

namespace CoreEx.Common.Tests
{
    /// <summary>
    /// A sample assembly weaver that modifies all types by implementing 
    /// the <see cref="INotifyPropertyChanged"/> interface.
    /// </summary>
    [Weaves("CoreEx.Samples.DomainModel.Implementation.dll")]
    public class SampleAssemblyWeaver : IAssemblyWeaver, IInitialize
    {
        /// <summary>
        /// Weaves the assembly represented by the <paramref name="assemblyDefinition"/> parameter.
        /// </summary>
        /// <param name="assemblyDefinition">The modified/weaved assembly.</param>
        public void Weave(AssemblyDefinition assemblyDefinition)
        {
            //Extract all the target types in the assembly.
            var targetTypes = assemblyDefinition.MainModule.Types.Cast<TypeDefinition>().Where(t => t.BaseType != null);

            var typesToImplement = new[] { typeof(INotifyPropertyChanged) };

            //Implement the interface for all target types
            targetTypes.ForEach(t => Implementor.Implement(t, typesToImplement));
        }

        /// <summary>
        /// Initializes this service instance.
        /// </summary>
        /// <param name="source">The <see cref="IServiceContainer"/> that created this service instance.</param>
        public void Initialize(IServiceContainer source)
        {
            Implementor = source.GetService<IImplementor>();
        }

        /// <summary>
        /// Gets or sets the <see cref="IImplementor"/> instance 
        /// that is responsible for implementing interfaces.
        /// </summary>
        public IImplementor Implementor { get; set; }
    }
}
